#include "TcpServer.hpp"
#include "Protocol.hpp"
#include "Calculator.hpp"
#include <memory>
#include <functional>

using namespace LockModule;
using cal_fun = std::function<Response(const Request &req)>;
class Parse
{
public:
    Parse(cal_fun c)
        : _cal(c)
    {}
    // package一定会有完整的报文吗？？不一定
    // 不完整->让底层继续读
    // 完整-> 提取 -> 反序列化 -> 得到结构化的Request -> 交给计算模块，进行处理
    std::string Entry(std::string &package)
    {
        // 服务器对单个报文处理的完整流程
        // 1. 判断报文的完整性！
        std::string message;
        // bool rs = Decode(package, &message);
        // if(!rs || message.empty())  return std::string();
        // // 2. 走到这里说明读到了完整报文，开始反序列化  --- 报文解析层
        // // 此时需要将Request的message反序列化成结构化字段
        // Request req;
        // if(!req.Deserialize(message))   return std::string();
        // // 3. 计算  --- 属应用层
        // // Response resp = _cal(req);
        // Response resp = gcal.Execute(req);
        // // 4. 服务端进行序列化  --- 报文解析层
        // std::string respstr;
        // resp.Serialize(respstr);
        // // 5. 添加报头
        // Encode(respstr);

        // 服务器对多个报文处理的完整流程
        std::string respstr;
        while (Decode(package, &message))
        {
            if (message.empty())
                break;
            // 2. 走到这里说明读到了完整报文，开始反序列化  --- 报文解析层
            // 此时需要将Request的message反序列化成结构化字段
            Request req;
            if (!req.Deserialize(message))
                break;
            // 3. 计算  --- 属应用层
            Response resp = _cal(req);
            // 4. 服务端进行序列化  --- 报文解析层
            std::string res;
            resp.Serialize(res);
            // 5. 添加报头
            Encode(res);

            // 6. 拼接应答
            respstr += res;
        }

        return respstr;
    }
private:
    cal_fun _cal;
};

int main()
{
    ENABLE_CONSOLE_LOG();

    // 1. 计算模块
    Calculator mycal;
    // 2. 解析对象
    Parse myparse([&mycal](const Request &req){
        return mycal.Execute(req);
    });
    // 3. 通信模块
    // Tcpserver只进行IO
    std::unique_ptr<Tcpserver> ts = std::make_unique<Tcpserver>([&myparse](std::string &package){
        return myparse.Entry(package);
    });

    ts->InitServer();
    ts->Start();

    return 0;
}